package com.swak.devtools.apidoc.parse.parser;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Map;

import com.swak.annotation.ApiDoc;
import com.swak.annotation.validate.Email;
import com.swak.annotation.validate.Length;
import com.swak.annotation.validate.Max;
import com.swak.annotation.validate.Min;
import com.swak.annotation.validate.NotNull;
import com.swak.annotation.validate.Phone;
import com.swak.annotation.validate.Regex;
import com.swak.devtools.apidoc.parse.ApiField;
import com.swak.devtools.apidoc.parse.ApiValidation;
import com.swak.utils.StringUtils;

public class FieldParser extends AbstractParser {

	private final Field field;
	private final Method method;
	private final Map<TypeVariable<?>, Type> paramVariablesMappers;
	private final ApiField apiField;

	public FieldParser(Field field, Method method, Map<TypeVariable<?>, Type> paramVariablesMappers) {
		this.field = field;
		this.method = method;
		this.paramVariablesMappers = paramVariablesMappers;
		this.apiField = new ApiField();
	}

	public ApiField parse() {

		// 注解
		Annotation[] annotations = field.getAnnotations();
		for (Annotation annotation : annotations) {
			if (annotation instanceof ApiDoc) {
				ApiDoc doc = (ApiDoc) annotation;
				apiField.setDesc(doc.value());
				apiField.setExample(doc.example());
			} else if (annotation instanceof Email) {
				Email anno = (Email) annotation;
				apiField.addValidation(
						new ApiValidation().setName(anno.annotationType().getSimpleName()).setMsg(anno.msg()));
			} else if (annotation instanceof Length) {
				Length anno = (Length) annotation;
				apiField.addValidation(new ApiValidation().setName(anno.annotationType().getSimpleName())
						.setValue(StringUtils.format("[%s, %s]", anno.min(), anno.max())).setMsg(anno.msg()));
			} else if (annotation instanceof Max) {
				Max anno = (Max) annotation;
				apiField.addValidation(new ApiValidation().setName(anno.annotationType().getSimpleName())
						.setValue(StringUtils.format("(~, %s]", anno.value())).setMsg(anno.msg()));
			} else if (annotation instanceof Min) {
				Min anno = (Min) annotation;
				apiField.addValidation(new ApiValidation().setName(anno.annotationType().getSimpleName())
						.setValue(StringUtils.format("[%s, ~]", anno.value())).setMsg(anno.msg()));
			} else if (annotation instanceof NotNull) {
				NotNull anno = (NotNull) annotation;
				apiField.addValidation(
						new ApiValidation().setName(anno.annotationType().getSimpleName()).setMsg(anno.msg()));
			} else if (annotation instanceof Phone) {
				Phone anno = (Phone) annotation;
				apiField.addValidation(
						new ApiValidation().setName(anno.annotationType().getSimpleName()).setMsg(anno.msg()));
			} else if (annotation instanceof Regex) {
				Regex anno = (Regex) annotation;
				apiField.addValidation(new ApiValidation().setName(anno.annotationType().getSimpleName())
						.setValue(StringUtils.format("/%s/", anno.value())).setMsg(anno.msg()));
			}
		}

		// 解析的结果
		Type type = method.getGenericParameterTypes()[0];
		Class<?> clazz = method.getParameterTypes()[0];
		ParsedClass parsedClass = parseClass(type, clazz, this.paramVariablesMappers);

		// 实际的类型
		apiField.setName(field.getName());
		apiField.setType(parsedClass.getParam().getClazz().getName());
		apiField.setApiClass(parsedClass.getApiClass());
		return apiField;
	}

	public static ApiField parse(Field field, Method method, Map<TypeVariable<?>, Type> paramVariablesMappers) {
		return new FieldParser(field, method, paramVariablesMappers).parse();
	}
}
